#include <QLabel>
#include <QLineEdit>
#include <QGroupBox>
#include <QCheckBox>
#include <QTabWidget>
#include <QPushButton>
#include <QGridLayout>
#include <QHeaderView>
#include <QTableWidget>
#include <QProgressBar>

#include "texmoduleregistereditor.h"

texModuleRegisterEditor::texModuleRegisterEditor()
{
    layout = new QGridLayout();
    createRegisterBoxen();
}

bool texModuleRegisterEditor::contentsChanged() const
{
    return changed;
}

void texModuleRegisterEditor::createRegisterBoxen()
{
    // module information
    grpModuleInformation = new QGroupBox(tr("Module Information"), this);
    grpModuleInformation->setCheckable(true);
    grpModuleInformation->setChecked(true);
    grpModuleInformation->setLayout(new QHBoxLayout);
    connect(grpModuleInformation, SIGNAL(toggled(bool)), this, SLOT(dataChanged()));

    lblBoardNumber = new QLabel(tr("Board #"), grpModuleInformation);
    boardNumber = new QLineEdit(grpModuleInformation);
    lblBoardNumber->setBuddy(boardNumber);
    boardNumber->setInputMask("00000");
    grpModuleInformation->layout()->addWidget(lblBoardNumber);
    grpModuleInformation->layout()->addWidget(boardNumber);
    connect(boardNumber, SIGNAL(textChanged(QString)), this, SLOT(dataChanged()));

    lblBoardRevision = new QLabel(tr("Revision"), grpModuleInformation);
    boardRevision = new QLineEdit(grpModuleInformation);
    lblBoardRevision->setBuddy(boardRevision);
    boardRevision->setInputMask(">Aaa");
    grpModuleInformation->layout()->addWidget(lblBoardRevision);
    grpModuleInformation->layout()->addWidget(boardRevision);
    connect(boardRevision, SIGNAL(textChanged(QString)), this, SLOT(dataChanged()));

    lblBoardConfiguration = new QLabel(tr("Conf"), grpModuleInformation);
    boardConfiguration = new QLineEdit(grpModuleInformation);
    lblBoardConfiguration->setBuddy(boardConfiguration);
    boardConfiguration->setInputMask("000");
    grpModuleInformation->layout()->addWidget(lblBoardConfiguration);
    grpModuleInformation->layout()->addWidget(boardConfiguration);
    connect(boardConfiguration, SIGNAL(textChanged(QString)), this, SLOT(dataChanged()));


    // codes
    grpCodes = new QGroupBox(tr("Codes"), this);
    grpCodes->setCheckable(true);
    grpCodes->setChecked(true);
    grpCodes->setLayout(new QHBoxLayout);
    connect(grpCodes, SIGNAL(toggled(bool)), this, SLOT(dataChanged()));

    for (int c=0; c<5; c++) {
        // instantiate the widgets
        lblCodes[c] = new QLabel(QString("C%1").arg(c+2), grpCodes);
        codes[c] = new QLineEdit(grpCodes);
        // setup the defaults
        lblCodes[c]->setBuddy(codes[c]);
        codes[c]->setValidator(new QRegExpValidator(QRegExp("[0-7]{3,3}"), codes[c]));
        // add them  to the layout
        grpCodes->layout()->addWidget(lblCodes[c]);
        grpCodes->layout()->addWidget(codes[c]);
        // setup connection to record changes
        connect(codes[c], SIGNAL(textChanged(QString)), this, SLOT(dataChanged()));
    }


    // scale & offset
    grpScale = new QGroupBox(tr("Scale"), this);
    grpScale->setCheckable(false);
    layoutScale = new QGridLayout;
    grpScale->setLayout(layoutScale);

    grpOffset = new QGroupBox(tr("Offset"), this);
    grpOffset->setCheckable(false);
    layoutOffset = new QGridLayout;
    grpOffset->setLayout(layoutOffset);

    for (int i=0; i < 8; i++) {
        // instantiate widgets (scale)
        lblScale[i] = new QLabel(QString("%1").arg(i+1), grpScale);
        checkScale[i] = new QCheckBox(grpScale);
        // setup defaults
        checkScale[i]->setChecked(true);
        scale[i] = new QLineEdit(grpScale);
        scale[i]->setInputMask("0000");
        // add to layout
        layoutScale->addWidget(lblScale[i], i, 0);
        layoutScale->addWidget(checkScale[i], i, 1);
        layoutScale->addWidget(scale[i], i, 2);
        // make connections
        connect(checkScale[i], SIGNAL(toggled(bool)), scale[i], SLOT(setEnabled(bool)));
        connect(checkScale[i], SIGNAL(toggled(bool)), this, SLOT(dataChanged()));
        connect(scale[i], SIGNAL(textChanged(QString)), this, SLOT(dataChanged()));

        // instantiate widgets (offset)
        lblOffset[i] = new QLabel(QString("%1").arg(i+1), grpOffset);
        checkOffset[i] = new QCheckBox(grpOffset);
        // setup defaults
        checkOffset[i]->setChecked(true);
        offset[i] = new QLineEdit(grpOffset);
        offset[i]->setInputMask("0000");
        // add to layout
        layoutOffset->addWidget(lblOffset[i], i, 0);
        layoutOffset->addWidget(checkOffset[i], i, 1);
        layoutOffset->addWidget(offset[i], i, 2);
        // make connections
        connect(checkOffset[i], SIGNAL(toggled(bool)), offset[i], SLOT(setEnabled(bool)));
        connect(checkOffset[i], SIGNAL(toggled(bool)), this, SLOT(dataChanged()));
        connect(offset[i], SIGNAL(textChanged(QString)), this, SLOT(dataChanged()));
    }


    // smart cal & smart reset


    // smart setup


    // lin tables
    tabWidgetLinTables = new QTabWidget(this);
    for (int i=0; i < 4; i++) {
        // instantiate the widgets
        layoutLinTable[i] = new QGridLayout;
        tabLinTable[i] = new QWidget(tabWidgetLinTables);
        linTable[i] = new QTableWidget(32, 2, tabWidgetLinTables);
        checkLinTable[i] = new QCheckBox(tr("Enabled"), tabLinTable[i]);
        loadLinTable[i] = new QPushButton(tr("Load"), tabLinTable[i]);
        saveLinTable[i] = new QPushButton(tr("Save"), tabLinTable[i]);
        // set the defaults
        checkLinTable[i]->setChecked(true);
        linTable[i]->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
        linTable[i]->setHorizontalHeaderLabels( QStringList() << "Input" << "Output" );
        for (int r=0; r < 32; r++) {
            for (int c=0; c < 2; c++) {
                QLineEdit *cell = new QLineEdit(linTable[i]);
                linTable[i]->setCellWidget(r, c, cell);
                cell->setInputMask("00000000");
                cell->setFrame(false);
                cell->setText("00000000");
            }
        }
        // add the tab
        tabWidgetLinTables->addTab(tabLinTable[i], QString("%1").arg(i+1));
        // assign the layout and add the widgets to it
        tabLinTable[i]->setLayout(layoutLinTable[i]);
        layoutLinTable[i]->addWidget(checkLinTable[i], 0, 0);
        layoutLinTable[i]->addWidget(loadLinTable[i], 0, 1);
        layoutLinTable[i]->addWidget(saveLinTable[i], 0, 2);
        layoutLinTable[i]->addWidget(linTable[i], 1, 0, 1, 3);
        // connect the checkbox enable/disable everything in this tab
        connect(checkLinTable[i], SIGNAL(toggled(bool)), linTable[i], SLOT(setEnabled(bool)));
        connect(checkLinTable[i], SIGNAL(toggled(bool)), loadLinTable[i], SLOT(setEnabled(bool)));
        connect(checkLinTable[i], SIGNAL(toggled(bool)), saveLinTable[i], SLOT(setEnabled(bool)));
        connect(checkLinTable[i], SIGNAL(toggled(bool)), this, SLOT(dataChanged()));
        connect(linTable[i], SIGNAL(cellChanged(int,int)), this, SLOT(dataChanged()));
    }


    // read / program meter buttons & progress bar
    read = new QPushButton(tr("&Read"), this);
    program = new QPushButton(tr("&Program"), this);
    progress = new QProgressBar(this);
    progress->setTextVisible(false);
    progress->setRange(0, 100);
    progress->setValue(0);
    connect(read, SIGNAL(clicked()), this, SLOT(readMeter()));
    connect(program, SIGNAL(clicked()), this, SLOT(programMeter()));


    // setup the main widget layout
    layout->addWidget(grpModuleInformation, 0, 0, 1, 2);
    layout->addWidget(grpCodes, 1, 0, 1, 2);
    layout->addWidget(grpScale, 2, 0);
    layout->addWidget(grpOffset, 2, 1);
    layout->addWidget(tabWidgetLinTables, 1, 2, 2, 2);
    layout->addWidget(progress, 3, 0, 1, 2);
    layout->addWidget(read, 3, 2);
    layout->addWidget(program, 3, 3);

    setLayout(layout);

    // default to nothing changed
    changed = false;
}

void texModuleRegisterEditor::dataChanged()
{
    // check for actual changes later??
    changed = true;

    if(changed) emit modified(true);
}
